package com.mit.wx.parser.impl;

import com.mit.wx.entity.Admin;
import com.mit.wx.service.AccessTokenService;
import com.mit.wx.service.AdminService;
import com.mit.wx.wx.WxKfApi;
import com.mit.wx.wx.dto.*;
import com.mit.wx.entity.AutoReplyRule;
import com.mit.wx.parser.WxMessageParser;
import com.mit.wx.service.AutoReplyRuleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 2018/10/13 Create by 郭文梁
 * <p>
 * WxMessageParserImpl
 * 微信消息解析器实现
 *
 * @author 郭文梁
 * @date 2018/10/13
 */
@Component
@Slf4j
public class WxMessageParserImpl implements WxMessageParser {
    /**
     * 默认回复规则
     */
    private static final String DEFAULT_REPLY = "无法理解的信息，已经为您转发到管理员微信。";
    private static final String ADMIN_MESSAGE_TEMPLATE = "来自:%s\r\n内容:%s";


    private final AutoReplyRuleService replyRuleService;
    private final AccessTokenService accessTokenService;
    private final AdminService adminService;

    @Autowired
    public WxMessageParserImpl(AutoReplyRuleService replyRuleService, AccessTokenService accessTokenService, AdminService adminService) {
        this.replyRuleService = replyRuleService;
        this.accessTokenService = accessTokenService;
        this.adminService = adminService;
    }

    @Override
    public TargetMessage parseMessage(SourceMessage sourceMessage) {
        AutoReplyRule rule = replyRuleService.findMatchingRule(sourceMessage.getContent());
        if (rule == null) {
            rule = replyRuleService.findContainRule(sourceMessage.getContent());
        }
        if (rule == null) {
            onUnknownMessage(sourceMessage);
            return buildDefaultReply(sourceMessage);
        }
        return process(sourceMessage, rule);
    }

    private TargetMessage process(SourceMessage sourceMessage, AutoReplyRule rule) {
        if (sourceMessage.getMsgType().equalsIgnoreCase(WxMessages.TYPE_TEXT)) {
            return buildReplyByRule(sourceMessage, rule);
        } else {
            onUnknownMessage(sourceMessage);
            return buildDefaultReply(sourceMessage);
        }
    }

    /**
     * 当有无法理解的消息时触发
     *
     * @param sourceMessage 源消息
     */
    private void onUnknownMessage(SourceMessage sourceMessage) {
        String content = sourceMessage.getContent();
        String from = sourceMessage.getFromUserName();

        String msg = String.format(ADMIN_MESSAGE_TEMPLATE, from, content);
        CustomerServiceMessage message = new CustomerServiceMessage();
        message.text(msg);
        sendMessage2Admin(message);
    }

    private void sendMessage2Admin(CustomerServiceMessage message) {
        List<Admin> admins = adminService.getBound();
        Set<String> openIds = admins.stream().map(Admin::getOpenId).collect(Collectors.toSet());
        log.debug("Found bound wechat account admin openIds:{}", openIds);
        for (String openId : openIds) {
            message.toUser(openId);
            try {
                BasicWxResponse resp = WxKfApi.sendKfMessage(accessTokenService.getAccessToken().getAccessToken(), message);
                log.debug("Send Unknown message to admin ,resp:{}", resp);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private TargetMessage buildReplyByRule(SourceMessage sourceMessage, AutoReplyRule rule) {
        TargetMessage result;
        switch (rule.getReplyType()) {
            case AutoReplyRule.IMAGE: {
                TargetImageMessage imageMessage = new TargetImageMessage();
                result = imageMessage;
                imageMessage.mediaId(rule.getMediaId());
                break;
            }
            case AutoReplyRule.VOICE: {
                TargetVoiceMessage voiceMessage = new TargetVoiceMessage();
                result = voiceMessage;
                voiceMessage.mediaId(rule.getMediaId());
                break;
            }
            case AutoReplyRule.VIDEO: {
                TargetVideoMessage videoMessage = new TargetVideoMessage();
                result = videoMessage;
                videoMessage.mediaId(rule.getMediaId())
                        .title(rule.getTitle())
                        .description(rule.getDescription());
                break;
            }
            case AutoReplyRule.NEWS: {
                TargetNewsMessage newsMessage = new TargetNewsMessage();
                result = newsMessage;
                TargetNewsMessage.Article article = new TargetNewsMessage.Article();
                article.setDescription(rule.getDescription());
                article.setPicUrl(rule.getPicUrl());
                article.setTitle(rule.getTitle());
                article.setUrl(rule.getUrl());
                newsMessage.addArticle(article);
                break;
            }
            case AutoReplyRule.TEXT: {
                TargetTextMessage textMessage = new TargetTextMessage();
                result = textMessage;
                textMessage.setContent(rule.getContent());
                break;
            }
            default: {
                result = null;
            }
        }
        if (result != null) {
            result.setCreateTime(String.valueOf(System.currentTimeMillis()));
            result.setFromUserName(sourceMessage.getToUserName());
            result.setToUserName(sourceMessage.getFromUserName());
        }
        return result;
    }

    private TargetMessage buildDefaultReply(SourceMessage message) {
        TargetTextMessage result = new TargetTextMessage();
        result.setCreateTime(String.valueOf(System.currentTimeMillis()));
        result.setContent(DEFAULT_REPLY);
        result.setFromUserName(message.getToUserName());
        result.setToUserName(message.getFromUserName());
        return result;
    }
}
